package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

func handleFunc(projName string, projSetting projSetting) func(http.ResponseWriter, *http.Request) {
	return func(resp http.ResponseWriter, re *http.Request) {
		defer re.Body.Close()
		lg.Info("hit %v", projName)

		body, err := readPushData(re.Body)
		if err != nil {
			fmt.Fprint(resp, "error")
			return
		}

		pd := new(pushdata)
		err = json.Unmarshal(body, pd)
		if err != nil {
			lg.Critical("unmarshal js error: %v", err)
			return
		}

		go func() {
			for _, v := range projSetting.Commands {

				var cmd *exec.Cmd
				spcmd := strings.Fields(v.Cmd)
				if len(spcmd) == 1 {
					cmd = exec.Command(spcmd[0])
				} else if len(spcmd) > 1 {
					cmd = exec.Command(spcmd[0], spcmd[1:]...)
				} else {
					continue
				}
				cmd.Dir = v.Path

				cmdName := filepath.Base(cmd.Path)

				lg.Info("running task %v's cmd %v", projName, cmdName)
				if v.Outlog != `` {
					f, err := os.OpenFile(v.Outlog, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0655)
					if err != nil {
						lg.Warn("cannot create outlog(%v) for %v", v.Outlog, cmdName)
						continue
					}
					defer f.Close()

					cmd.Stderr = f
					cmd.Stdout = f

				} else {
					lg.Info("%v's outlog not set. skip", cmdName)
				}

				if v.PushData {
					cmd.Stdin = bytes.NewBuffer(body)
				} else {
					lg.Info("%v's donesn't need push data. skip", cmdName)
				}

				err = cmd.Run()
				if err != nil {
					lg.Critical("cannot run command: %v: %v", cmd.Path, err)
				}

				lg.Info("command %v finished", cmdName)

			}
		}()

		fmt.Fprint(resp, "ok")

	}
}

func readPushData(reader io.Reader) ([]byte, error) {
	body, err := ioutil.ReadAll(reader)
	if err != nil {
		lg.Critical("Read push data fail: %v", err)
		return nil, err
	}

	body = body[5:] // 去掉开头的hook=

	js, err := url.QueryUnescape(string(body))
	if err != nil {

		lg.Critical("Unescape push data fail: %v", err)
		return nil, err
	}

	return []byte(js), nil
}
